import { model_reqBaseURL, other_reqBaseURL } from "../config";
import MyRequest, { getRequestKey } from "@/lib/util/axios";
import { AxiosError, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from "axios";
import { logError, logSpecial } from "../io/log";
import crypto from 'crypto';
import { baseId, urlToConfig } from "../config";
import { OtherReqBase } from "@/types/api/other"
import 'server-only'//代表仅服务端可使用


/**后端 - 向py服务器请求的扩展类 */
class PyRequest extends MyRequest {
    /**以form形式进行post请求，同时把第二个参数封装成JSON后作为 json_data 参数传递 （向建文服务器请求的固定格式，有method和params）
     * @param url 请求路径
     * @param method 请求method，会包裹成json_data，放在 method 中，为undefined的话就不添加进对象里
     * @param params 请求数据，会包裹成json_data，放在 params 中
     * @param config 其它配置 
     * @template T 返回数据的ts提示
     * @template D 请求数据的ts提示
     * @example 最终形式：
     * {
     * --json_data: JSON.stringify({
     * -------method: method
     * -------params: params
     * --})
     * }
     */
    public async postByJsonData<T = any, D = Record<string, any>>(url: string, method: string | undefined, params: D, config: AxiosRequestConfig = {}): Promise<OtherReqBase<T>> {
        return new Promise(async (resolve, reject) => {
            try {
                const res = await this.postByForm<OtherReqBase<T>, { json_data: string }>(url, { json_data: JSON.stringify({ method, params }) }, config)
                resolve(res)
            } catch (error: any) {
                reject(error) //这里复用postByForm，所以返回error就整个返回
            }
        })
    }
}


/**服务端 - 向建文服务器请求的axios实例。禁止在客户端使用，以免本文件的重要配置泄露！ */
const otherRequest = new PyRequest({ baseURL: other_reqBaseURL }, (config) => {
    let url = config.url

    if (url) {
        if (url.startsWith(model_reqBaseURL)) {
            url = url.replace(model_reqBaseURL, '')
        }
        const urlArr = url.split('/')
        const baseUrl = urlArr[0] || urlArr[1] //url可能是 /aaa/xxxxx，也可能是 aaa/xxxxx，我们目的是拿到aaa

        if (baseUrl in urlToConfig) {
            const { ak, sk, id } = urlToConfig[baseUrl as keyof typeof urlToConfig]
            config.headers!.Authorization = getAuthorization(ak, sk, id);
        } else {
            if (!url.includes('http://172.30.10.139')) //暂时屏蔽这个提示
                logError(`路径${baseUrl}不在配置urlToConfig中`)
        }
        /** 权限控制 */
        if (url.includes('http://172.30.10.139:8003')) {
            const { ak, sk, id } = urlToConfig.public_resource //暂时需要手动添加鉴权 
            config.headers!.Authorization = getAuthorization(ak, sk, id);
        }
    }
}, [(res: AxiosResponse) => res.data,
(err: AxiosError) => {
    logError('响应拦截器 - ', err.message)
    if (err.code === 'ERR_CANCELED') {
        return Promise.reject('请求重复，取消');
    }
    return Promise.reject(err);
},
])
/**向建文服务器请求 - 生成aksk鉴权 */
export const getAuthorization = (ak: string, sk: string, id: number) => {
    const time = new Date().getTime()
    //拿到配置后，生成token 。 生成token的方法问@建文
    const signature = crypto.createHash('sha256').update(`${ak}/${time}/${sk}`).digest('hex') //生成签名 
    return [ak, time, signature, id, baseId].join('/')
}

export default otherRequest




